﻿using System;
using UnityEngine;
using UnityEngine.SceneManagement;


namespace xres
{


    public class SceneLoader : BaseLoader
    {
        public const string Err_Load_Bundle = "Err_Load_Bundle";

        readonly BundleLoader _bundleLoader;

        readonly string _sceneName = "";

        readonly LoadSceneMode _sceneMode;

        AsyncOperation _op;


        public SceneLoader(BundleLoader loader, string sceneName, bool addictive)
        {
            //#如果scene直接打在Build Settings中(不需要热更)这种, 直接用SceneManager.LoadScene
            //和SceneManager.LoadSceneAsync, 不需要用Loader了
            if (null == loader)
                throw new NullReferenceException("loader null");

            _bundleLoader = loader;
            _sceneName = sceneName;
            _sceneMode = addictive ? LoadSceneMode.Additive : LoadSceneMode.Single; //todo: 这次MainScene addictive了, 下次可以single么?
        }

        public float CheckProgress()
        {
            switch (_state)
            {
            case LoaderState.Init:
                return 0;

            case LoaderState.LoadAssetBundle:
                return _bundleLoader.CheckProgress() * 0.5f;

            case "LoadScene":
                return 0.5f + _op.progress;

            }

            return 1;
        }

        public void Load(bool async)
        {
            if (LoaderState.Finish == _state)
            {
                if (string.IsNullOrEmpty(ErrType)) //成功加载完毕, 直接切换场景
                {
                    if (async)
                        LoadSceneAsync();
                    else
                        LoadSceneSync();

                    return;
                }

                Debug.Log($"SceneLoader: last load err, not try again");
                return;
            }

            switch (_state)
            {
            case LoaderState.Init:
            case LoaderState.Finish:
                var mode = async ? LoadMode.Async : LoadMode.Sync;

                if (async)
                    LoadAsync();
                else
                    LoadSync();
                return;
            }

            //加载中切换加载模式无效
        }


        //========== sync

        void LoadSync()
        {
            if (LoaderState.Init == _bundleLoader._state)
                _bundleLoader.Load(false);
            else if (LoaderState.Finish != _bundleLoader._state)
                throw new Exception($"scene bundle: {_sceneName} load in async mode, and not load finish");

            LoadSceneSync();
        }

        void LoadSceneSync()
        {
            SceneManager.LoadScene(_sceneName, _sceneMode);
            SetError("", "");
            SetFinishAndNotify("");
        }

        //==========

        //========== async 

        void LoadAsync()
        {
            if (!_bundleLoader.IsLoadFinish())
            {
                Debug.Log($"SceneLoader: bundle in loading, wait it: {_bundleLoader._bundleName}");
                _state = LoaderState.LoadAssetBundle;
                _bundleLoader.onComplete.AddListener(OnComplete_Bundle);
            }
            else //bundle已加载完毕
            {
                OnComplete_Bundle(null, "", null);
            }
        }

        void OnComplete_Bundle(object obj, string type, object data)
        {
            if (true) Debug.Log($"SceneLoader: scene bundle finish");

            if (!string.IsNullOrEmpty(_bundleLoader.ErrType))
            {
                SetError(Err_Load_Bundle, $"bundle load fail, scene will not load");
                SetFinishAndNotify(ErrMsg);
                return;
            }
            LoadSceneAsync();
        }

        void LoadSceneAsync()
        {
            if (true) Debug.Log($"SceneLoader: LoadSceneAsync: {_sceneName}");

            _state = "LoadScene";
            var request = SceneManager.LoadSceneAsync(_sceneName, _sceneMode);
            _op = request;
            request.completed += OnComplete_LoadScene;
        }

        void OnComplete_LoadScene(AsyncOperation op)
        {
            _op = null;

            if (false) Debug.Log($"SceneLoader: complete LoadScene");

            SetError("", "");
            SetFinishAndNotify("");
        }

        //==========


    } //end of class


}

